/************************************************************
	File:		ParticleSystem.cpp
	Author:		Mitchel Mishiev
	Purpose:	CParticleSystem class loads up the particles of the Game
************************************************************/

#include "ParticleSystem.h"
#include "../../SGD Wrappers/CSGD_Direct3D.h"
#include "../../SGD Wrappers/CSGD_DirectInput.h"
#include "../../SGD Wrappers/CSGD_TextureManager.h"
#include "../../SGD Wrappers/CSGD_XAudio2.h"
#include "../../SGD Wrappers/SGD_String.h"
#include "../TinyXML/tinyxml.h"
#include <cmath>
using namespace std;

#define TM CSGD_TextureManager::GetInstance()
#define D3 CSGD_Direct3D::GetInstance()

CParticleSystem::CParticleSystem(void)
{

}


CParticleSystem::~CParticleSystem(void)
{
	for ( unsigned int i = 0; i < EmitterList.size(); ++i )
	{
		TM->UnloadTexture(EmitterList[i]->GetID());

		delete EmitterList[i];
		EmitterList[i] = nullptr;
	}

}

void CParticleSystem::Update( float fElaspedTime )
{
	for( unsigned int i = 0; i < EmitterList.size(); i++ )
	{
		for( unsigned int j = 0; j < EmitterList[i]->GetParticles().size(); ++j)
		{
			//Life Adjustor
			//Check to see if the currentlife is zero
			if( EmitterList[i]->GetParticles()[j]->GetCurrentLife() <= 0.0f )
			{
				//Reset the CurrentLife
				//EmitterList[i]->GetParticles()[j]->SetCurrentLife( (float)(rand() % (int)EmitterList[i]->GetMaxLife() ) );
				EmitterList[i]->GetParticles()[j]->SetCurrentLife( 0 );

				//Reset The Position
				/*EmitterList[i]->GetParticles()[j]->SetpX( EmitterList[i]->GetX() + ( rand() % EmitterList[i]->GetWidth() ) );
				EmitterList[i]->GetParticles()[j]->SetpX( EmitterList[i]->GetX() + ( rand() % EmitterList[i]->GetWidth() ) );*/
			}
			else
			{
				//Count the CurrentLife Down
				EmitterList[i]->GetParticles()[j]->SetCurrentLife( EmitterList[i]->GetParticles()[j]->GetCurrentLife() - fElaspedTime );
			}

			//Color Adjustor
			EmitterList[i]->GetParticles()[j]->SetColorAlpha( ( EmitterList[i]->GetEndColorAlpha() - EmitterList[i]->GetStartColorAlpha() ) * ( EmitterList[i]->GetParticles()[j]->GetCurrentLife() / EmitterList[i]->GetMaxLife() ) + EmitterList[i]->GetStartColorAlpha() ); 
			EmitterList[i]->GetParticles()[j]->SetColorRed( ( EmitterList[i]->GetEndColorRed() - EmitterList[i]->GetStartColorRed() ) * ( EmitterList[i]->GetParticles()[j]->GetCurrentLife() / EmitterList[i]->GetMaxLife() ) + EmitterList[i]->GetStartColorRed() ); 
			EmitterList[i]->GetParticles()[j]->SetColorGreen( ( EmitterList[i]->GetEndColorGreen() - EmitterList[i]->GetStartColorGreen() ) * ( EmitterList[i]->GetParticles()[j]->GetCurrentLife() / EmitterList[i]->GetMaxLife() ) + EmitterList[i]->GetStartColorGreen() ); 
			EmitterList[i]->GetParticles()[j]->SetColorBlue( ( EmitterList[i]->GetEndColorBlue() - EmitterList[i]->GetStartColorBlue() ) * ( EmitterList[i]->GetParticles()[j]->GetCurrentLife() / EmitterList[i]->GetMaxLife() ) + EmitterList[i]->GetStartColorBlue() ); 

			//Velocity Adjustor
			EmitterList[i]->GetParticles()[j]->SetCurrentVelocityX( ( EmitterList[i]->GetEndVelocityX() - EmitterList[i]->GetStartVelocityX() ) * ( EmitterList[i]->GetParticles()[j]->GetCurrentLife() / EmitterList[i]->GetMaxLife() ) + EmitterList[i]->GetStartVelocityX() );
			EmitterList[i]->GetParticles()[j]->SetCurrentVelocityY( ( EmitterList[i]->GetEndVelocityY() - EmitterList[i]->GetStartVelocityY() ) * ( EmitterList[i]->GetParticles()[j]->GetCurrentLife() / EmitterList[i]->GetMaxLife() ) + EmitterList[i]->GetStartVelocityY() );

			//Position Adjustor
			EmitterList[i]->GetParticles()[j]->SetpX( EmitterList[i]->GetParticles()[j]->GetpX() + EmitterList[i]->GetParticles()[j]->GetCurrentVelocityX()  * fElaspedTime );
			EmitterList[i]->GetParticles()[j]->SetpY( EmitterList[i]->GetParticles()[j]->GetpY() + EmitterList[i]->GetParticles()[j]->GetCurrentVelocityY()  * fElaspedTime );	

			//Rotation Adjustor
			EmitterList[i]->GetParticles()[j]->SetCurrentRotation( ( EmitterList[i]->GetEndRotation() - EmitterList[i]->GetStartRotation() ) * ( EmitterList[i]->GetParticles()[j]->GetCurrentLife() / EmitterList[i]->GetMaxLife() ) + EmitterList[i]->GetStartRotation() );

			//Scale Adjustor
			EmitterList[i]->GetParticles()[j]->SetCurrentScaleX( ( EmitterList[i]->GetEndScaleX() - EmitterList[i]->GetStartScaleX() ) * ( EmitterList[i]->GetParticles()[j]->GetCurrentLife() / EmitterList[i]->GetMaxLife() ) + EmitterList[i]->GetStartScaleX() );
			EmitterList[i]->GetParticles()[j]->SetCurrentScaleY( ( EmitterList[i]->GetEndScaleY() - EmitterList[i]->GetStartScaleY() ) * ( EmitterList[i]->GetParticles()[j]->GetCurrentLife() / EmitterList[i]->GetMaxLife() ) + EmitterList[i]->GetStartScaleY() );

		}
	}
}

void CParticleSystem::Render()
{
	for(unsigned int i = 0; i < EmitterList.size(); i++ )
	{
		for( unsigned int j =0; j <  EmitterList[i]->GetParticles().size(); ++j)
		{
			if( EmitterList[i]->GetParticles()[j]->GetCurrentLife() != 0 )
			{
				//Render the particles
				TM->Draw( EmitterList[i]->GetID(), EmitterList[i]->GetParticles()[j]->GetpX(), EmitterList[i]->GetParticles()[j]->GetpY(), EmitterList[i]->GetParticles()[j]->GetCurrentScaleX(),
					EmitterList[i]->GetParticles()[j]->GetCurrentScaleX(), NULL, 1.0f, 1.0f, EmitterList[i]->GetParticles()[j]->GetCurrentRotation(),
								D3DCOLOR_ARGB( (int)EmitterList[i]->GetParticles()[j]->GetColorAlpha(), (int)EmitterList[i]->GetParticles()[j]->GetColorRed(),
													(int)EmitterList[i]->GetParticles()[j]->GetColorGreen(), (int)EmitterList[i]->GetParticles()[j]->GetColorBlue() ) ); 
			}
		}
	}
}
bool CParticleSystem::LoadParticles( const char* filename )
{
	//Create EmitterData Storage
	EmitterData info;

	// Create a TinyXML document
	TiXmlDocument doc;

	// Attempt to load from the file
	if( doc.LoadFile( filename ) == false )
		return false;

	// Access the root element
	TiXmlElement* pRoot = doc.RootElement();	

	if( pRoot == nullptr )
		return false;

	// Find the Emiiter Element
	TiXmlElement* pEmitter = pRoot->FirstChildElement( "Emitter" );

	while( pEmitter != nullptr )
	{
		//Create Emitter
		CEmitter* emitter = new CEmitter();

		//Read Attributes
		pEmitter->Attribute("MaxParticle", &info.mParticle );
		pEmitter->Attribute("positionx", &info.x );
		pEmitter->Attribute("positiony", &info.y );
		pEmitter->Attribute("width", &info.width );
		pEmitter->Attribute("height", &info.height );

		const char* temp1 = pEmitter->Attribute( "ImageID" );

		if( temp1 != nullptr )
		{
			wchar_t* temp2 = new wchar_t[ strlen(temp1) + 1 ];

			//When the updated SGD wrapper is installed, get rid of the * 2 
			CSTR_TO_TSTR (temp2, ((strlen(temp1) + 1) * 2), temp1);
			emitter->SetID( TM->LoadTexture( temp2 ) );

			delete [] temp2;
		}

		pEmitter->Attribute("minLife", &info.minLife );
		pEmitter->Attribute("maxLife", &info.maxLife );
		pEmitter->Attribute("minVelocityX", &info.eVelocityX );
		pEmitter->Attribute("maxVelocityX", &info.sVelocityX );
		pEmitter->Attribute("minVelocityY", &info.eVelocityY );
		pEmitter->Attribute("maxVelocityY", &info.sVelocityY );
		pEmitter->Attribute("minRotation", &info.eRotation );
		pEmitter->Attribute("maxRotation", &info.sRotation );
		pEmitter->Attribute("minScaleX", &info.eScaleX );
		pEmitter->Attribute("maxScaleX", &info.sScaleX );
		pEmitter->Attribute("minScaleY", &info.eScaleY );
		pEmitter->Attribute("maxScaleY", &info.sScaleY );
		pEmitter->Attribute("minColorA", &info.eColorAlpha);
		pEmitter->Attribute("maxColorA", &info.sColorAlpha);
		pEmitter->Attribute("minColorR", &info.eColorRed );
		pEmitter->Attribute("maxColorR", &info.sColorRed );
		pEmitter->Attribute("minColorG", &info.eColorGreen );
		pEmitter->Attribute("maxColorG", &info.sColorGreen );
		pEmitter->Attribute("minColorB", &info.eColorBlue );
		pEmitter->Attribute("maxColorB", &info.sColorBlue );

		//Send data to the emitter
		emitter->SetMaxParticle( info.mParticle );
		emitter->SetX( info.x );
		emitter->SetY( info.y );
		emitter->SetWidth( info.width );
		emitter->SetHeight( info.height );
		emitter->SetMaxLife( (float)info.maxLife );
		emitter->SetMinLife( (float)info.minLife );
		emitter->SetStartVelocityX( (float)info.sVelocityX );
		emitter->SetEndVelocityX( (float)info.eVelocityX );
		emitter->SetStartVelocityY( (float)info.sVelocityY );
		emitter->SetEndVelocityY( (float)info.eVelocityY );
		emitter->SetStartRotation( (float)info.sRotation );
		emitter->SetEndRotation( (float)info.eRotation );
		emitter->SetStartScaleX( (float)info.sScaleX );
		emitter->SetEndScaleX( (float)info.eScaleX );
		emitter->SetStartScaleY( (float)info.sScaleY );
		emitter->SetEndScaleY( (float)info.eScaleY );
		emitter->SetStartColorAlpha( (float)info.sColorAlpha );
		emitter->SetEndColorAlpha( (float)info.eColorAlpha );
		emitter->SetStartColorRed( (float)info.sColorRed );
		emitter->SetEndColorRed( (float)info.eColorRed );
		emitter->SetStartColorGreen( (float)info.sColorGreen );
		emitter->SetEndColorGreen( (float)info.eColorGreen );
		emitter->SetStartColorBlue( (float)info.sColorBlue );
		emitter->SetEndColorBlue( (float)info.eColorBlue );

		//Setup the Particle List
		emitter->SetupParticleList( emitter );

		//Add emitter to the list
		SetEmitterList( emitter );

		//Move to the next node
		pEmitter = pEmitter->NextSiblingElement( "Emitter" );
		
	}

	return ( GetEmitterList().size() > 0 );
}

